package com.hh.demo.service;

import com.hh.demo.entity.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static java.lang.Thread.sleep;


@Service
@EnableScheduling//开启定时任务
public class ClientService {
    Logger logger = LoggerFactory.getLogger(ClientService.class);
    //与服务器异步通信的Channel
    private AsynchronousSocketChannel channel;
    //private final String address = "172.16.1.29";
//    private final String address = "192.168.1.200";
//    private final String port = "6004";
    private final String address = "172.16.1.13";
    private final String port = "6004";

    @Resource
    private SimpMessagingTemplate simpMessagingTemplate;
    @Resource
    private BookService bookService;
    @Resource
    private UserService userService;
    @Resource
    private BookinfoService bookinfoService;

    /**
     * socket连接
     */
    public void connect() throws Exception {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        ExecutorService pool = Executors.newFixedThreadPool(5);
        //以指定线程池来创建一一个AsynchronousChannelGroup
        AsynchronousChannelGroup channelGroup = AsynchronousChannelGroup.withThreadPool(pool);
        //以channelGroup作为组管理器来创建AsynchronousSocketChannel
        channel = AsynchronousSocketChannel.open(channelGroup);
        channel.connect(new InetSocketAddress(address, Integer.parseInt(port))).get(3, TimeUnit.SECONDS);
        buffer.clear();
        channel.read(buffer, null, new CompletionHandler<Integer, Object>() {
            private int countNull;//记录传递过来的数据是空的次数
            private long currentTime = System.currentTimeMillis();

            @Override
            public void completed(Integer result, Object attachment) {
                buffer.flip();
                //接收到的硬件的数据  content
                String content = StandardCharsets.UTF_8.decode(buffer).toString().trim();
                maxCount(content);
                try {
                    logger.info("===========" + content);//打印输出内容

                    Exceptionmessage exceptionmessage = new Exceptionmessage();
                    Smokesensor smokesensor = new Smokesensor();
                    Book book = new Book();
                    Date date = new Date();
                    User user = new User();
                    Bookinfo bookinfo = new Bookinfo();
                    SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
                    String borrower = null;
                    //烟雾传感器 ：Hwdga0401 000.0T
                    if (content.matches("Hwdga0401.{5}T")) {
                       String sen = content.substring(9,14);
                       if("000.0".equals(sen)){//正常
                           smokesensor.setData(sen);
                           smokesensor.setRecordTime(String.valueOf(date));
                           String sensor = "正常";
                           simpMessagingTemplate.convertAndSend("/topic/sensor",sensor);
                           simpMessagingTemplate.convertAndSend("/topic/time2",format.format(date));
                       }else {//异常
                           smokesensor.setData(sen);
                           smokesensor.setRecordTime(String.valueOf(date));
                           String sensor = "异常";
                           simpMessagingTemplate.convertAndSend("/topic/sensor",sensor);
                           simpMessagingTemplate.convertAndSend("/topic/time2",format.format(date));
                       }
                    } //录入失败帧：Hwclr0302onT
                    else if (content.matches("Hwclr0302onT")) {
                        String fail = "超时，录入失败";
                        simpMessagingTemplate.convertAndSend("/topic/fail",fail);

                    }//非法闯入：Hwdhi02010onT
                    else if (content.matches("Hwdhi020.{4}T")) {
                        String ill = content.substring(9,10);
                        if(content.contains("on")) {//开馆状态
                            simpMessagingTemplate.convertAndSend("/topic/state", "开馆");
                            simpMessagingTemplate.convertAndSend("/topic/time1", format.format(date));
                            if ("0".equals(ill)) {//正常
                                exceptionmessage.setData(ill);
                                exceptionmessage.setRecordTime(String.valueOf(date));
                                String sensor = "正常";
                                simpMessagingTemplate.convertAndSend("/topic/illegal", sensor);
                                simpMessagingTemplate.convertAndSend("/topic/time4", format.format(date));
                            }
                        } else {
                                simpMessagingTemplate.convertAndSend("/topic/state", "闭馆");
                                simpMessagingTemplate.convertAndSend("/topic/time1", format.format(date));
                                if ("0".equals(ill)) {//正常
                                    exceptionmessage.setData(ill);
                                    exceptionmessage.setRecordTime(String.valueOf(date));
                                    String sensor = "正常";
                                    simpMessagingTemplate.convertAndSend("/topic/illegal", sensor);
                                    simpMessagingTemplate.convertAndSend("/topic/time4", format.format(date));
                                } else {//有人闯入
                                    exceptionmessage.setData(ill);
                                    exceptionmessage.setRecordTime(String.valueOf(date));
                                    String sensor = "有人闯入";
                                    simpMessagingTemplate.convertAndSend("/topic/illegal", sensor);
                                    simpMessagingTemplate.convertAndSend("/topic/time4", format.format(date));
                                }
                        }

                    }//人员出入 : Hwdif040800000000T
                    else if (content.matches("Hwdif0408.{8}T")) {
                       String user1 = content.substring(9,17);
                       //刷卡信息和数据库中的卡号进行对比，若是存在，就允许人员进入
                       if(userService.isExistUser(user1)){
                           String message ="Hwcld0402onT";//成功返回
                           System.out.println("-------------------------------------");
                           AsynchronousSocketChannel channel = getChannel();
                           sleep(1000);
                           channel.write(ByteBuffer.wrap(message.getBytes(StandardCharsets.UTF_8)));
                       }
                    }//图书录入:Hwdib030800000000T
                    else if(content.matches("Hwdib0308.{8}T")){
                        String bookCard = content.substring(9,17);
                        if(bookinfoService.isExistBook(bookCard)){
                            //数据库中存在该卡号
                            String str = "该卡号已被记录";
                            simpMessagingTemplate.convertAndSend("/topic/str",str);
                        }else{
                            bookinfo.setBookCard(bookCard);
                            simpMessagingTemplate.convertAndSend("/topic/bookCard",bookCard);
                        }
                    }//用户录入:Hwdid030800000000T
                    else if(content.matches("Hwdid0308.{8}T")){
                        String userCard = content.substring(9,17);
                        if(userService.isExistUser(userCard)){
                            //数据库中存在该卡号
                            String str = "该卡号已被记录";
                            simpMessagingTemplate.convertAndSend("/topic/str",str);
                        }else{
                            user.setUserCard(userCard);
                            simpMessagingTemplate.convertAndSend("/topic/userCard",userCard);
                        }
                    }//用户借阅或者归还图书发送的用户信息：Hwdjd030800000000T
                    else if(content.matches("Hwdjd0308.{8}T")){
                        String userCardMsg = content.substring(9,17);
                        simpMessagingTemplate.convertAndSend("/topic/userCardMsg",userCardMsg);
                    }//用户借阅或者归还图书发送的图书信息：Hwdjb030800000000T
                    else if(content.matches("Hwdjb0308.{8}T")) {
                        String bookCardMsg = content.substring(9, 17);
                        simpMessagingTemplate.convertAndSend("/topic/bookCardMsg",bookCardMsg);
                    }//超过十秒未刷卡 Hwdsb0302loseT
                    else if(content.matches("Hwdsb0302loseT")){
                        String str1 = "超过十秒未刷卡";
                        simpMessagingTemplate.convertAndSend("/topic/str1",str1);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                buffer.clear();
                try {
                    channel.read(buffer, null, this);
                } catch (NullPointerException n) {
                    logger.error(n.getMessage());
                }
            }

            //假设服务器掉线情况，就会发送无数垃圾数据过来，导致程序卡顿，这里检测发送过来的短时间内的次数，超过十次就让它断开连接
            private void maxCount(String content) {
                if ("".equals(content)) {
                    if (System.currentTimeMillis() - currentTime < 500) {
                        countNull++;
                    } else {
                        countNull = 0;
                    }
                    currentTime = System.currentTimeMillis();
                    if (countNull > 10) {
                        try {
                            disConnect();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        logger.error("超过十次没有收到空数据,就退出");
                    }
                }
            }

            @Override
            public void failed(Throwable exc, Object attachment) {
                System.out.println("控制台连接退出");
            }
        });
    }

    @Scheduled(fixedRate = 10000)     //每间隔10秒执行一次, 检查是否掉线, 是就让它重新连接至服务器
    private void configureTasks() {
        if (channel == null || !channel.isOpen()) {
            try {
                connect();
            } catch (Exception e) {
                logger.error(e.getMessage());
            }
        }
    }

    /**
     * 关闭连接
     */
    public void disConnect() throws IOException {
        if (this.channel != null && channel.isOpen()) {
            channel.shutdownInput();
            channel.shutdownOutput();
            channel.close();
            channel = null;
        }
    }
    /**
     * 该对象销毁（Build）时，销毁与服务器连接
     */
    @PreDestroy
    public void detroyComponent() throws IOException {
        disConnect();
    }

    public AsynchronousSocketChannel getChannel() {
        return channel;
    }
}
